package io.renren.modules.haiyou.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.Query;
import io.renren.modules.haiyou.dao.PictureDao;
import io.renren.modules.haiyou.dao.SceneDao;
import io.renren.modules.haiyou.dao.SceneTagDao;
import io.renren.modules.haiyou.entity.Picture;
import io.renren.modules.haiyou.entity.Scene;
import io.renren.modules.haiyou.entity.SceneTag;
import io.renren.modules.haiyou.entity.dto.Eat;
import io.renren.modules.haiyou.entity.dto.Live;
import io.renren.modules.haiyou.entity.dto.Play;
import io.renren.modules.haiyou.service.SceneService;
import io.renren.modules.haiyou.utils.mapperUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;


@Service("sceneService")
public class SceneServiceImpl extends ServiceImpl<SceneDao, Scene> implements SceneService {

    @Resource
    private PictureDao pictureDao;
    @Resource
    private SceneTagDao sceneTagDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<Scene> page = this.page(
                new Query<Scene>().getPage(params),
                new QueryWrapper<Scene>()
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(Scene entity) {
        String id = IdWorker.getIdStr();
        entity.setId(id);
        entity.setAddTime(new Date());
        mapperUtils.associatePicturesAndEntity(entity, pictureDao);
        mapManyToMany(entity.getTagIds(), id);
        return SqlHelper.retBool(baseMapper.insert(entity));
    }

    private void mapManyToMany(List<String> tagIds, String id) {
        // 删除旧的tag
        sceneTagDao.delete(new QueryWrapper<SceneTag>().lambda().eq(SceneTag::getSceneId, id));
        // 关联新的
        SceneTag sceneTag = new SceneTag();
        sceneTag.setSceneId(id);
        if (!CollectionUtil.isEmpty(tagIds)) {
            for (String tagId : tagIds) {
                sceneTag.setTagId(tagId);
                sceneTagDao.insert(sceneTag);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(Scene entity) {
        mapperUtils.associatePicturesAndEntity(entity, pictureDao);
        mapManyToMany(entity.getTagIds(), entity.getId());

        // 先将修改前的所有pic SurroundingPic变为0
        Scene scene = baseMapper.selectById(entity.getId());
        if (scene != null) {
            changePicToSurroundingPic(scene, 0);
        }

        // 再将每个图片变为SurroundingPic, 不被定时任务删除
        changePicToSurroundingPic(entity, 1);

        return SqlHelper.retBool(baseMapper.updateById(entity));
    }

    private void changePicToSurroundingPic(Scene entity, Integer state) {
        String eat = entity.getSurroundingEat();
        String live = entity.getSurroundingLive();
        String play = entity.getSurroundingPlay();

        changePicToSurroundingPic(eat, Eat.class, state);
        changePicToSurroundingPic(live, Live.class, state);
        changePicToSurroundingPic(play, Play.class, state);
    }


    /**
     * 将周边pic变为 state
     *
     * @param surrounding
     * @param clazz
     * @param state
     * @param <T>
     */
    private <T> void changePicToSurroundingPic(String surrounding, Class<T> clazz, Integer state) {
        if (!StrUtil.isBlank(surrounding)) {
            ArrayList<T> eats = JSONUtil.parseArray(surrounding).toList(clazz);
            for (T e : eats) {
                // 将每个eat的图片变为SurroundingPic, 不被定时任务删除
                try {
                    Method method = clazz.getDeclaredMethod("getPics");
                    String picsStr = (String) method.invoke(e);
                    List<String> pics = Arrays.asList(picsStr.split(";"));
                    pictureDao.update(null, new LambdaUpdateWrapper<Picture>()
                            .in(Picture::getId, pics)
                            .set(Picture::getSurroundingPic, state));
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException noSuchMethodException) {
                    noSuchMethodException.printStackTrace();
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            return false;
        }
        return SqlHelper.retBool(baseMapper.deleteBatchIds(idList));
    }

}